package com.robusta.app.model.spreadsheet.persistence;

import com.robusta.app.domain.spreadsheet.Model;
import com.robusta.app.domain.validation.ValidationResultContainer;
import com.robusta.app.model.persistence.AuditListener;
import com.robusta.app.model.persistence.Creatable;
import com.robusta.app.model.persistence.Updatable;
import com.robusta.spreadsheet.describe.ColumnInfo;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.hibernate.annotations.Type;

import javax.persistence.*;
import java.io.Serializable;

import static com.google.common.base.Strings.isNullOrEmpty;

@Entity @Table(name = "FIELD") @EntityListeners(AuditListener.class)
public class PersistableField extends com.robusta.app.model.persistence.Entity implements Model.Field, ValidationResultContainer, Serializable, Creatable, Updatable {
    @Id
    @Column(name = "FIELD_ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "FIELD_NAME", nullable = false)
    private String name;
    @Column(name = "FIELD_VALUE", nullable = false)
    private String value;
    @Column(name = "IS_KEY", nullable = false)
    @Type(type = "yes_no")
    private boolean key;
    @Column(name = "VALIDATION_MESSAGE", nullable = true)
    private String validationMessage;
    @ManyToOne
    @JoinColumn(name="MODEL_ID", nullable=false)
    private PersistableModel model;

    public PersistableField() {
    }

    public PersistableField(String value, ColumnInfo metadata) {
        this(metadata.modelFieldName(), value, metadata.isKey());
    }

    public PersistableField(String name, String value, boolean key) {
        this.name = name;
        this.value = value;
        this.key = key;
    }

    public boolean isKey() {
        return key;
    }

    public String getValidationMessage() {
        return validationMessage;
    }

    public void setValidationMessage(String validationMessage) {
        this.validationMessage = validationMessage;
    }

    @Override
    public boolean isValid() {
        return isNullOrEmpty(validationMessage);
    }

    @Override
    public void setValid(boolean valid) {
        // No op. presence/absence of validation message drives this.
    }

    public PersistableModel getModel() {
        return model;
    }

    public void setModel(PersistableModel model) {
        this.model = model;
    }

    @Override
    public String getFieldName() {
        return name;
    }

    @Override
    public String getFieldValue() {
        return value;
    }

    @Override
    public String toString() {
        return new ReflectionToStringBuilder(this).toString();
    }

    @Override
    public boolean equals(Object that) {
        return EqualsBuilder.reflectionEquals(this, that, "model");
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this, "model");
    }
}
